
using System;
using UMC.Net;
using System.Text;

namespace UMC.ITME
{

    public class HttpReplacer
    {

        static byte[] strHttps = UTF8Encoding.ASCII.GetBytes("https://");
        static byte[] strHttp = UTF8Encoding.ASCII.GetBytes("http://");
        static byte[] httpsEncode = UTF8Encoding.ASCII.GetBytes(Uri.EscapeDataString("https://"));
        static byte[] httpEncode = UTF8Encoding.ASCII.GetBytes(Uri.EscapeDataString("http://"));
        static byte[] strEncodePort = UTF8Encoding.ASCII.GetBytes("%3A");
        public static byte[] HtmlHeadEnd = UTF8Encoding.ASCII.GetBytes("</head>");

        static byte[] Equals16 = SiteConfig.Hex(new byte[] { 61 });
        static byte[] Point16 = SiteConfig.Hex(new byte[] { 46 });

        byte[] nowScheme;
        byte[] nowSchemeEncode;
        NetWriteData _writer;
        SiteConfig.ReplaceSetting replaceSetting;
        int _srcIndex, _destIndex;
        // string _headKey;
        HttpProxy _proxy;
        int _maxLength;
        int _minLength, _minHexLength;
        byte[] buffer;

        bool isFind = false;
        bool isPort = false;
        bool isEncodePort = false;
        int bufferSize = 0;
        int bufferStart = 0;

        // bool isHead;
        Func<bool, bool> _check;
        public HttpReplacer(HttpProxy proxy, NetWriteData writer, SiteConfig.ReplaceSetting setting, int srcIndex, int destIndex)
        {
            this._proxy = proxy;
            this._writer = writer;
            this.replaceSetting = setting;
            this._destIndex = destIndex;
            this._srcIndex = srcIndex;

            var hLength = proxy.Site.MainHost.Hosts[srcIndex].Length;
            _minLength = proxy.Site.IsUnion ? Math.Min(hLength, proxy.Site.SuffixHost.Hosts[srcIndex].Length) : hLength;

            if (replaceSetting != null)
            {
                _check = proxy.Site.IsUnion ? CheckUnionSetting : CheckSetting;
                foreach (var hv in replaceSetting.Domains.Span)
                {
                    var item = hv.Hosts[srcIndex];
                    if (item.Length > hLength)
                    {
                        hLength = item.Length;
                    }
                    if (item.Length < _minLength)
                    {
                        _minLength = item.Length;
                    }
                }
            }
            else
            {
                _check = proxy.Site.IsUnion ? EndUnionWith : Check;
            }


            if (proxy.Context.Scheme.Length > 4)
            {
                this.nowScheme = strHttps;
                this.nowSchemeEncode = httpsEncode;
            }
            else
            {
                this.nowScheme = strHttp;
                this.nowSchemeEncode = httpEncode;

            }
            this._maxLength = hLength * 4 + 8;

            this.buffer = new byte[_maxLength];
            this._minHexLength = _minLength * 4;
        }

        int Read(NetReadData reader)
        {
            if (bufferSize == _maxLength)
            {
                _writer(buffer, 0, 1);
                Array.Copy(buffer, 1, buffer, 0, bufferSize - 1);
                bufferSize--;
                if (bufferStart > 0)
                {
                    bufferStart--;
                }
            }
            return reader(buffer, bufferSize, 1);
        }
        static bool EndsWith(byte[] buffer, int bl, Span<byte> end)
        {
            return EndsWith(buffer, 0, bl, end);
        }
        static bool EndsWith(byte[] buffer, int offset, int size, Span<byte> end)
        {
            var el = end.Length;
            if (el <= size)
            {
                offset = offset + size - el;
                for (var i = 0; i < el; i++)
                {
                    if (end[i] != buffer[offset + i])
                    {
                        return false;
                    }
                }
                return true;
            }
            return false;
        }

        static bool EndsWithIgnoreCase(byte[] buffer, int offset, int size, Span<byte> end)
        {
            var el = end.Length;
            if (el <= size)
            {
                offset = offset + size - el;
                for (var i = 0; i < el; i++)
                {
                    if (Utility.IgnoreCase(end[i], buffer[offset + i]) == false)
                    {

                        return false;
                    }
                }
                return true;
            }
            return false;
        }

        byte lastByte;

        bool isHead = true;
        public void Html(StringValue jsKey, NetReadData reader)
        {
            byte value;
            int len;
            while ((len = Read(reader)) > 0)
            {
                value = buffer[bufferSize];
                bufferSize++;
                switch (value)
                {
                    case 0:
                        if (len > 1)
                            bufferSize--;
                        goto case 20;
                    case 20:
                    default:
                        is16 = false;
                        len16 = 0;
                        bufferStart = 0;
                        isEncodePort = false;
                        isPort = false;
                        _writer(buffer, 0, bufferSize);
                        lastByte = buffer[bufferSize - 1];
                        bufferSize = 0;
                        isFind = false;
                        continue;
                    case 60://<
                        if (isHead)
                        {
                            continue;
                        }
                        else
                        {
                            goto case 20;
                        }
                    case 62://>
                        if (isHead && EndsWith(buffer, bufferSize, HtmlHeadEnd))
                        {
                            is16 = false;
                            isHead = false;
                            bufferSize = bufferSize - HtmlHeadEnd.Length;
                            _writer(buffer, 0, bufferSize);

                            var bData = UTF8Encoding.ASCII.GetBytes($"<script src=\"/UMC.Conf/{_proxy.Site.Root}/{_proxy.MD5(String.Empty)}/{HttpProxy.MD5(jsKey)}.js\"></script>\r\n</head>");
                            _writer(bData, 0, bData.Length);
                            bufferSize = 0;
                            bufferStart = 0;
                            continue;

                        }
                        goto case 20;
                    case 58://':':
                        if (isFind)
                        {
                            is16 = false;
                            isFind = false;
                            isPort = true;
                            bufferSize--;
                            continue;
                        }
                        else
                        {
                            bufferStart = bufferSize;
                            goto case 122;
                        }

                    case 37://'%':
                        if (isFind)
                        {
                            is16 = false;
                            isPort = false;
                            isFind = false;
                            isEncodePort = true;
                            continue;
                        }
                        else
                        {
                            bufferStart = bufferSize;
                            goto case 122;
                        }
                    case 48://0
                    case 49://1
                    case 50://2
                    case 51://3
                    case 52://4
                    case 53://5
                    case 54://6
                    case 55://7
                    case 56://8
                    case 57://9
                        if (isPort)
                        {
                            bufferSize--;
                            continue;
                        }
                        goto case 100;
                    case 65://A
                    case 66://B
                    case 67://C
                    case 68://D
                    case 69://E
                    case 70://F
                        if (is16)
                        {
                            if (len16 == 2 || len16 == 3)
                            {
                                len16++;
                                if (len16 == 4)
                                {
                                    if (_minHexLength > bufferSize)
                                    {
                                        continue;
                                    }
                                    break;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                len16 = 0;
                            }
                        }
                        bufferStart = bufferSize;
                        goto case 122;
                    case 47://“/”
                        bufferStart = bufferSize;
                        goto case 122;
                    case 92://"\"
                        if (is16 && len16 == 4)
                        {
                            len16 = 1;
                        }
                        else
                        {
                            is16 = true;
                            len16 = 1;
                            bufferStart = 0;
                            isEncodePort = false;
                            isPort = false;
                            _writer(buffer, 0, bufferSize - 1);
                            bufferSize = 1;
                            buffer[0] = value;
                            isFind = false;
                        }
                        continue;
                    // break;
                    case 120://x
                        if (is16)
                        {
                            if (len16 == 1)
                            {
                                len16++;
                                continue;
                            }
                            else
                            {
                                len16 = 0;
                            }
                        }
                        goto case 122;
                    // break;
                    case 97://a
                    case 98://b
                    case 99://c
                    case 100://d
                    case 101://e
                    case 102://f
                        if (is16)
                        {
                            if (len16 == 2 || len16 == 3)
                            {
                                len16++;
                                if (len16 == 4)
                                {
                                    if (_minHexLength > bufferSize)
                                    {
                                        continue;
                                    }
                                    break;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                len16 = 0;
                            }
                        }
                        goto case 122;

                    case 45://-
                    case 46://.
                            // case 47://“/”
                            // case 97://a
                            // case 98://b
                            // case 99://c
                            // case 100://d
                            // case 101://e
                            // case 102://f
                    case 103://g
                    case 104://h
                    case 105://i
                    case 106://j
                    case 107://k
                    case 108://l
                    case 109://m
                    case 110://n
                    case 111://o
                    case 112://p
                    case 113://q
                    case 114://r
                    case 115://s
                    case 116://t
                    case 117://u
                    case 118://v
                    case 119://w
                    case 121://y
                    case 122://z
                        is16 = false;
                        if (isEncodePort && bufferSize == 3)
                        {
                            isEncodePort = false;
                            if (EndsWith(buffer, bufferSize, strEncodePort))
                            {
                                isPort = true;
                                bufferSize = 0;
                                bufferStart = 0;
                            }
                            continue;
                        }
                        isPort = false;


                        if (_minLength > bufferSize - bufferStart)
                        {
                            continue;
                        }
                        break;

                }
                isFind = _check(is16);

            }

        }

        bool is16 = false;
        int len16 = 0;
        public void Append(HttpAppender appender, NetReadData reader)
        {
            byte value;
            int len;
            while (appender.IsStop == false && (len = Read(reader)) > 0)
            {
                value = buffer[bufferSize];
                bufferSize++;
                switch (value)
                {
                    case 0:
                        if (len > 1)
                            bufferSize--;
                        goto case 20;
                    case 20:
                    default:
                        is16 = false;
                        len16 = 0;
                        bufferStart = 0;
                        isEncodePort = false;
                        isPort = false;
                        _writer(buffer, 0, bufferSize);
                        lastByte = buffer[bufferSize - 1];
                        bufferSize = 0;
                        isFind = false;
                        continue;
                    case 10:
                        if (appender.Index == appender.AppendIndex)
                        {
                            appender.Append(_writer);
                        }
                        appender.Index++;

                        goto case 20;
                    // break;
                    case 58://':':
                        if (isFind)
                        {
                            is16 = false;
                            isFind = false;
                            isPort = true;
                            bufferSize--;
                            continue;
                        }
                        else
                        {
                            bufferStart = bufferSize;
                            goto case 122;
                        }

                    case 37://'%':
                        if (isFind)
                        {
                            is16 = false;
                            isPort = false;
                            isFind = false;
                            isEncodePort = true;
                            continue;
                        }
                        else
                        {
                            bufferStart = bufferSize;
                            goto case 122;
                        }
                    case 48://0
                    case 49://1
                    case 50://2
                    case 51://3
                    case 52://4
                    case 53://5
                    case 54://6
                    case 55://7
                    case 56://8
                    case 57://9
                        if (isPort)
                        {
                            bufferSize--;
                            continue;
                        }
                        goto case 100;
                    case 65://A
                    case 66://B
                    case 67://C
                    case 68://D
                    case 69://E
                    case 70://F
                        if (is16)
                        {
                            if (len16 == 2 || len16 == 3)
                            {
                                len16++;
                                if (len16 == 4)
                                {
                                    if (_minHexLength > bufferSize)
                                    {
                                        continue;
                                    }
                                    break;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                len16 = 0;
                            }
                        }
                        bufferStart = bufferSize;
                        goto case 122;
                    case 47://“/”
                        bufferStart = bufferSize;
                        goto case 122;
                    case 92://"\"
                        if (is16 && len16 == 4)
                        {
                            len16 = 1;
                        }
                        else
                        {
                            is16 = true;
                            len16 = 1;
                            bufferStart = 0;
                            isEncodePort = false;
                            isPort = false;
                            _writer(buffer, 0, bufferSize - 1);
                            bufferSize = 1;
                            buffer[0] = value;
                            isFind = false;
                        }
                        continue;
                    // break;
                    case 120://x
                        if (is16)
                        {
                            if (len16 == 1)
                            {
                                len16++;
                                continue;
                            }
                            else
                            {
                                len16 = 0;
                            }
                        }
                        goto case 122;
                    // break;
                    case 97://a
                    case 98://b
                    case 99://c
                    case 100://d
                    case 101://e
                    case 102://f
                        if (is16)
                        {
                            if (len16 == 2 || len16 == 3)
                            {
                                len16++;
                                if (len16 == 4)
                                {
                                    if (_minHexLength > bufferSize)
                                    {
                                        continue;
                                    }
                                    break;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                len16 = 0;
                            }
                        }
                        goto case 122;

                    case 45://-
                    case 46://.
                            // case 47://“/”
                            // case 97://a
                            // case 98://b
                            // case 99://c
                            // case 100://d
                            // case 101://e
                            // case 102://f
                    case 103://g
                    case 104://h
                    case 105://i
                    case 106://j
                    case 107://k
                    case 108://l
                    case 109://m
                    case 110://n
                    case 111://o
                    case 112://p
                    case 113://q
                    case 114://r
                    case 115://s
                    case 116://t
                    case 117://u
                    case 118://v
                    case 119://w
                    case 121://y
                    case 122://z
                        is16 = false;
                        if (isEncodePort && bufferSize == 3)
                        {
                            isEncodePort = false;
                            if (EndsWith(buffer, bufferSize, strEncodePort))
                            {
                                isPort = true;
                                bufferSize = 0;
                                bufferStart = 0;
                            }
                            continue;
                        }
                        isPort = false;


                        if (_minLength > bufferSize - bufferStart)
                        {
                            continue;
                        }
                        break;

                }
                isFind = _check(is16);

            }

        }




        public void Replace(NetReadData reader)
        {
            byte value;
            int len;
            while ((len = Read(reader)) > 0)
            {
                value = buffer[bufferSize];
                bufferSize++;
                switch (value)
                {
                    case 0:
                        if (len > 1)
                            bufferSize--;
                        goto case 20;
                    case 20:
                    default:
                        is16 = false;
                        len16 = 0;
                        bufferStart = 0;
                        isEncodePort = false;
                        isPort = false;
                        _writer(buffer, 0, bufferSize);
                        lastByte = buffer[bufferSize - 1];
                        bufferSize = 0;
                        isFind = false;
                        continue;
                    case 58://':':
                        if (isFind)
                        {
                            is16 = false;
                            isFind = false;
                            isPort = true;
                            bufferSize--;
                            continue;
                        }
                        else
                        {
                            bufferStart = bufferSize;
                            goto case 122;
                        }

                    case 37://'%':
                        if (isFind)
                        {
                            is16 = false;
                            isPort = false;
                            isFind = false;
                            isEncodePort = true;
                            continue;
                        }
                        else
                        {
                            bufferStart = bufferSize;
                            goto case 122;
                        }
                    case 48://0
                    case 49://1
                    case 50://2
                    case 51://3
                    case 52://4
                    case 53://5
                    case 54://6
                    case 55://7
                    case 56://8
                    case 57://9
                        if (isPort)
                        {
                            bufferSize--;
                            continue;
                        }
                        goto case 100;
                    case 65://A
                    case 66://B
                    case 67://C
                    case 68://D
                    case 69://E
                    case 70://F
                        if (is16)
                        {
                            if (len16 == 2 || len16 == 3)
                            {
                                len16++;
                                if (len16 == 4)
                                {
                                    if (_minHexLength > bufferSize)
                                    {
                                        continue;
                                    }
                                    break;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                len16 = 0;
                            }
                        }
                        bufferStart = bufferSize;
                        goto case 122;
                    case 47://“/”
                        bufferStart = bufferSize;
                        goto case 122;
                    case 92://"\"
                        if (is16 && len16 == 4)
                        {
                            len16 = 1;
                        }
                        else
                        {
                            is16 = true;
                            len16 = 1;
                            bufferStart = 0;
                            isEncodePort = false;
                            isPort = false;
                            _writer(buffer, 0, bufferSize - 1);
                            bufferSize = 1;
                            buffer[0] = value;
                            isFind = false;
                        }
                        continue;
                    // break;
                    case 120://x
                        if (is16)
                        {
                            if (len16 == 1)
                            {
                                len16++;
                                continue;
                            }
                            else
                            {
                                len16 = 0;
                            }
                        }
                        goto case 122;
                    // break;
                    case 97://a
                    case 98://b
                    case 99://c
                    case 100://d
                    case 101://e
                    case 102://f
                        if (is16)
                        {
                            if (len16 == 2 || len16 == 3)
                            {
                                len16++;
                                if (len16 == 4)
                                {
                                    if (_minHexLength > bufferSize)
                                    {
                                        continue;
                                    }
                                    break;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                len16 = 0;
                            }
                        }
                        goto case 122;

                    case 45://-
                    case 46://.
                            // case 47://“/”
                            // case 97://a
                            // case 98://b
                            // case 99://c
                            // case 100://d
                            // case 101://e
                            // case 102://f
                    case 103://g
                    case 104://h
                    case 105://i
                    case 106://j
                    case 107://k
                    case 108://l
                    case 109://m
                    case 110://n
                    case 111://o
                    case 112://p
                    case 113://q
                    case 114://r
                    case 115://s
                    case 116://t
                    case 117://u
                    case 118://v
                    case 119://w
                    case 121://y
                    case 122://z
                        is16 = false;
                        if (isEncodePort && bufferSize == 3)
                        {
                            isEncodePort = false;
                            if (EndsWith(buffer, bufferSize, strEncodePort))
                            {
                                isPort = true;
                                bufferSize = 0;
                                bufferStart = 0;
                            }
                            continue;
                        }
                        isPort = false;


                        if (_minLength > bufferSize - bufferStart)
                        {
                            continue;
                        }
                        break;

                }
                isFind = _check(is16);

            }

        }

        bool Check(bool is16)
        {
            return EndWith(this._proxy.Site.MainHost, is16);
        }
        bool CheckSetting(bool is16)
        {
            foreach (var hem in replaceSetting.Domains.Span)
            {
                if (EndWith(hem, is16))
                {
                    return true;
                }
            }
            return EndWith(this._proxy.Site.MainHost, is16);

        }
        bool CheckUnionSetting(bool is16)
        {
            foreach (var hem in replaceSetting.Domains.Span)
            {
                if (EndWith(hem, is16))
                {
                    return true;
                }
            }
            return EndUnionWith(is16);

        }
        public const byte BytePOINT = 46;
        bool EndUnionWith(bool is16)
        {
            var hem = this._proxy.Site.SuffixHost;
            var khost = hem.Hosts[_srcIndex];
            if (is16)
            {
                var hosthex = hem.Hex[_srcIndex];
                if (EndsWithIgnoreCase(buffer, 0, bufferSize, hosthex))
                {

                    bufferStart = 0;
                    bufferSize = bufferSize - hosthex.Length;
                    if (bufferSize >= 4)
                    {
                        if (Utility.EqualIgnoreCase(buffer.AsSpan(bufferSize - 4, 4), Point16))
                        {
                            var dest = _proxy.Site.MainHost.Hex[_destIndex];
                            if (bufferSize >= 8)
                            {
                                var bs = buffer.AsSpan(bufferSize - 8, 4);
                                if (Utility.EqualIgnoreCase(bs, Equals16))
                                {
                                    _writer(buffer, 0, bufferSize - 4);
                                    int start = Utility.FindIgnoreCase(dest, Point16);

                                    _writer(dest, start, dest.Length - start);
                                }
                                else
                                {
                                    _writer(buffer, 0, bufferSize - 4);
                                    _writer(dest, 0, dest.Length);
                                }
                            }
                            else
                            {
                                int start = Utility.FindIgnoreCase(dest, Point16);
                                _writer(dest, start, dest.Length - start);
                            }
                            bufferSize = 0;
                            return true;
                        }
                    }

                    _writer(buffer, 0, bufferSize);
                    _writer(hem.Hex[_destIndex], 0, hem.Hex[_destIndex].Length);
                    bufferSize = 0;

                    return true;
                }
                else
                {
                    return false;
                }
            }
            else if (EndsWith(buffer, bufferStart, bufferSize - bufferStart, khost))
            {
                bufferStart = 0;
                bufferSize = bufferSize - khost.Length;
                if (bufferSize > 0)
                {

                    var b = buffer[bufferSize - 1];
                    var kmhost = _proxy.Site.MainHost.Hosts[_srcIndex];
                    if (b == kmhost[kmhost.Length - khost.Length - 1])
                    {

                        bufferSize--;
                        hem = _proxy.Site.MainHost;

                        if (b == BytePOINT)
                        {
                            if (bufferSize == 0)
                            {
                                switch (lastByte)
                                {
                                    case 42:
                                    case 39:
                                    case 61:
                                    case 34:
                                        var dest2 = hem.Hosts[_destIndex];
                                        int index = Array.IndexOf(dest2, BytePOINT);//  dest.IndexOf(46)
                                        if (index > 0)
                                        {
                                            _writer(dest2, index, dest2.Length - index);
                                        }
                                        else
                                        {
                                            _writer(dest2, 0, dest2.Length);
                                        }
                                        bufferSize = 0;
                                        return true;
                                }
                            }


                        }
                    }
                }
                else
                {

                    switch (lastByte)
                    {
                        // case 42:
                        // case 39:
                        case 61:
                            // case 34:
                            var dest2 = _proxy.Site.MainHost.Hosts[_destIndex];
                            int index = Array.IndexOf(dest2, BytePOINT);//  dest.IndexOf(46)
                            if (index > 0)
                            {
                                _writer(dest2, index + 1, dest2.Length - index - 1);
                            }
                            else
                            {
                                _writer(dest2, 0, dest2.Length);
                            }
                            bufferSize = 0;
                            return true;
                    }

                }


                if (EndsWith(buffer, bufferSize, strHttps))
                {
                    bufferSize = bufferSize - strHttps.Length;
                    _writer(buffer, 0, bufferSize);
                    _writer(nowScheme, 0, nowScheme.Length);
                }
                else if (EndsWith(buffer, bufferSize, strHttp))
                {
                    bufferSize = bufferSize - strHttp.Length;
                    _writer(buffer, 0, bufferSize);
                    _writer(nowScheme, 0, nowScheme.Length);
                }
                else if (EndsWith(buffer, bufferSize, httpsEncode))
                {
                    bufferSize = bufferSize - httpsEncode.Length;
                    _writer(buffer, 0, bufferSize);
                    _writer(nowSchemeEncode, 0, nowSchemeEncode.Length);
                }
                else if (EndsWith(buffer, bufferSize, httpEncode))
                {
                    bufferSize = bufferSize - httpEncode.Length;
                    _writer(buffer, 0, bufferSize);
                    _writer(nowSchemeEncode, 0, nowSchemeEncode.Length);
                }
                else
                {
                    _writer(buffer, 0, bufferSize);
                }
                var dest = hem.Hosts[_destIndex];
                _writer(dest, 0, dest.Length);
                bufferSize = 0;
                return true;

            }
            return false;
        }

        bool EndWith(SiteConfig.HostConvert hem, bool is16)
        {
            var khost = hem.Hosts[_srcIndex];
            if (is16)
            {
                var hosthex = hem.Hex[_srcIndex];
                if (EndsWithIgnoreCase(buffer, 0, bufferSize, hosthex))
                {

                    bufferStart = 0;
                    bufferSize = bufferSize - hosthex.Length;
                    _writer(buffer, 0, bufferSize);
                    _writer(hem.Hex[_destIndex], 0, hem.Hex[_destIndex].Length);
                    bufferSize = 0;
                    return true;
                }
                else
                {
                    return false;

                }
            }
            else if (EndsWith(buffer, bufferStart, bufferSize - bufferStart, khost))
            {
                bufferStart = 0;

                bufferSize = bufferSize - khost.Length;
                if (EndsWith(buffer, bufferSize, strHttps))
                {
                    bufferSize = bufferSize - strHttps.Length;
                    _writer(buffer, 0, bufferSize);
                    _writer(nowScheme, 0, nowScheme.Length);
                }
                else if (EndsWith(buffer, bufferSize, strHttp))
                {
                    bufferSize = bufferSize - strHttp.Length;
                    _writer(buffer, 0, bufferSize);
                    _writer(nowScheme, 0, nowScheme.Length);
                }
                else if (EndsWith(buffer, bufferSize, httpsEncode))
                {
                    bufferSize = bufferSize - httpsEncode.Length;
                    _writer(buffer, 0, bufferSize);
                    _writer(nowSchemeEncode, 0, nowSchemeEncode.Length);
                }
                else if (EndsWith(buffer, bufferSize, httpEncode))
                {
                    bufferSize = bufferSize - httpEncode.Length;
                    _writer(buffer, 0, bufferSize);
                    _writer(nowSchemeEncode, 0, nowSchemeEncode.Length);
                }
                else
                {
                    _writer(buffer, 0, bufferSize);

                }
                var dest = hem.Hosts[_destIndex];
                _writer(dest, 0, dest.Length);
                bufferSize = 0;
                return true;
            }
            return false;
        }
        public void Flush()
        {
            if (bufferSize > 0)
            {
                _writer(buffer, 0, bufferSize);
            }
        }

    }
}